#pragma once

#ifndef ELL_MEMPOOL_H
#define ELL_MEMPOOL_H

#include <stdlib.h>

struct ell__mempool_chunk;

struct ell_mempool {
    size_t element_size;
    size_t chunk_size;
    size_t num_chunks;
    size_t capacity; /*!< number of elements allocated */
    size_t size;     /*!< number of elements used */

    struct ell__mempool_chunk* chunks;
    void* next_free;
};

void ell_mempool_init(struct ell_mempool* pool, size_t element_size);
void ell_mempool_init2(struct ell_mempool* pool, size_t element_size, size_t reserve);
void ell_mempool_init3(struct ell_mempool* pool,
  size_t element_size,
  size_t reserve,
  size_t chunk_size);

void ell_mempool_free(struct ell_mempool* pool);

void ell_mempool_reserve(struct ell_mempool* pool, size_t reserve);

/* Memory management */

void* ell_mempool_get(struct ell_mempool* pool);
void ell_mempool_ret(struct ell_mempool* pool, void* ptr);

/* Queries */

size_t ell_mempool_size(const struct ell_mempool* pool);
size_t ell_mempool_capacity(const struct ell_mempool* pool);

/* Typedefs */

#ifdef ELL_CONVENIENCE_TYPEDEFS

#ifndef ELL_CONVENIENCE_TYPEDEF_SUFFIX
#define ELL_CONVENIENCE_TYPEDEF_SUFFIX _t
#endif

#define ELL__CONVENIENCE_TYPEDEF_PASTER(x, y) x##y
#define ELL__CONVENIENCE_TYPEDEF_EVAL(x, y) ELL__CONVENIENCE_TYPEDEF_PASTER(x, y)
#define ELL_CONVENIENCE_TYPEDEF(type)                                                              \
    ELL__CONVENIENCE_TYPEDEF_EVAL(type, ELL_CONVENIENCE_TYPEDEF_SUFFIX)

typedef struct ell_mempool ELL_CONVENIENCE_TYPEDEF(ell_mempool);

#endif

#endif
